#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>

#include "Inet_Addr.hpp"
#include "ThreadPool.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"

using task_t = std::function<void()>;

class Route
{
private:
    void CheckOnlineUser(Inet_Addr &who)
    {
        LockGuard lockguard(&_mutex);
        for (auto &user : _online_user)
        {
            if (user == who)
            {
                LOG(DEBUG, "%s 存在\n", who.AddrStr().c_str());
                return; // 存在啥都不做
            }
        }

        // 不存在，添加
        _online_user.emplace_back(who);
        LOG(DEBUG, "%s 不存在，添加\n", who.AddrStr().c_str());
    }

    void offline(Inet_Addr &who)
    {
        LockGuard lockguard(&_mutex);
        auto iter = _online_user.begin();
        for (; iter != _online_user.end(); ++iter)
        {
            if (*iter == who)
            {
                LOG(DEBUG, "%s quit....\n", who.AddrStr().c_str());
                _online_user.erase(iter);
                break; // 避免迭代器失效
            }
        }
    }

    void ForwardHelper(int socket, const std::string &message, Inet_Addr &who)
    {
        LockGuard lockguard(&_mutex);
        std::string send_message = "[" + who.AddrStr() + "]# " + message;
        for (auto &user : _online_user)
        {
            struct sockaddr_in peer = user.Addr();
            ::sendto(socket, send_message.c_str(), send_message.size(), 0, (struct sockaddr *)&peer, sizeof(peer));
            LOG(DEBUG, "forward message to %s, message is %s\n", who.AddrStr().c_str(), send_message.c_str());
        }
    }

public:
    Route()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }

    void ForWard(int socket, const std::string &message, Inet_Addr &who)
    {
        // 判断用户是否在用户列表 --> 1、存在，不处理 2、不存在，添加
        CheckOnlineUser(who);
        // 判断用户是否退出
        if (message == "Q" || message == "QUIT")
        {
            offline(who);
        }

        // 使用线程池进行转发和路由
        task_t t = std::bind(&Route::ForwardHelper, this, socket, message, who);
        ThreadPool<task_t>::getInstance()->PushTask(t);
    }

    ~Route()
    {
        pthread_mutex_destroy(&_mutex);
    }

private:
    std::vector<Inet_Addr> _online_user; // 在线用户列表
    pthread_mutex_t _mutex;              // 互斥锁
};